#ifndef BUFFER_H
#define BUFFER_H
#include <cstring>
#include <iostream>
#include <unistd.h>
#include <sys/uio.h>
#include <vector>
#include <atomic>
#include <assert.h>

class Buffer
{
public:
    Buffer(int initBuffSize = 1024);
    ~Buffer() = default;

    size_t WritebleBytes() const;       // 返回当前可写字节数，即从writePos_到vector容器末尾的可用空间大小
    size_t ReadableBytes() const;       // 返回当前可读字节数，即从readPos_到writePos_之间的数据长度
    size_t PrependableBytes() const;    // 返回当前可预留字节数，即从buffer_开始到readPos_之前的可用空间大小

    const char* Peek() const;           // 返回指向当前可读数据起始位置的指针，但不改变读写位置
    void EnsureWriteable(size_t len);   // 确保缓冲区至少有len字节的可写空间，若不足，则进行扩容
    void HasWritten(size_t len);        // 标记已向缓冲区写入len字节的数据

    void Retrive(size_t len);           // 从缓冲区读取指定长度len的数据，并移动读位置
    void RetriveUntil(const char* end); // 从缓冲区读取直到某个终止符的数据，并移动读位置

    void RetriveAll();                  // 清空缓冲区，将读写指针都置为0，并清空缓冲区内容
    std::string RetriveAllToStr();      // 将当前可读数据转化为字符串并返回，然后执行RetriveAll()
    std::string RetriveAllToStrConst() const;      // 将当前可读数据转化为字符串并返回

    // 分别返回指向当前可写位置的常量和非常量指针
    const char* BeginWriteConst() const;
    char* BeginWrite();

    // Append 系列函数：将字符串、字符数组或其他 Buffer 对象中的数据追加到当前缓冲区。
    void Append(const std::string& str);
    void Append(const char* str, size_t len);
    void Append(const void* data, size_t len);
    void Append(const Buffer& buff);

    // 从文件描述符 fd 读取数据至缓冲区，或将缓冲区数据写入 fd。同时，通过引用参数 Errno 返回错误代码。
    ssize_t ReadFd(int fd, int* Errno);
    ssize_t WriteFd(int fd, int* Errno);

private:
    char* BeginPtr_();              // 返回 buffer_ 的起始地址（考虑线程安全）
    const char* BeginPtr_() const;  // 返回 buffer_ 的起始地址（考虑线程安全）

    void MakeSpace_(size_t len);    // 在需要预留空间时，对缓冲区进行调整，确保有足够的空间容纳新数据。

    std::vector<char> buffer_;              // 具体装数据的vector
    std::atomic<std::size_t> readPos_;      // 读的位置
    std::atomic<std::size_t> writePos_;     // 写的位置

};

#endif  //BUFFER_H